package leetcode.part2;

import org.junit.Test;

public class KMP {
    public int strStr(String haystack, String needle) {
        int[] next = next(needle);
        int j = 0;
        int i = 0;
        for (; i < haystack.length(); i++) {
            if (j == needle.length()) return i - j;
            if (haystack.charAt(i) == needle.charAt(j)) {
                j++;
            } else {
                while (j > 0 && haystack.charAt(i) != needle.charAt(j)) {
                    j = next[j - 1];
                }
                // 最后判断h[i]和n[j]是否相同，如果相同就j++，继续比较；因为此时h[i]和n[j]相同，需要提前挪动j，让两者在正确的位置比较
                // 如果不同，这时j=0，不用动j
                if (haystack.charAt(i) == needle.charAt(j)) {
                    j++;
                }

            }
        }
        if (j == needle.length()) return i - j;

        return -1;
    }

    /**
     * 构建next数组
     * 使用双指针
     *
     * @param s
     * @return
     */
    private int[] next(String s) {
        int len = s.length();
        // i是左指针，j是右指针
        int i = 0;
        int j = 1;
        int[] next = new int[len];
        next[0] = 0;
        while (i < len && j < len) {
            // 如果左右指针相同就同时移动，并且当前右指针为左指针index+1
            if (s.charAt(i) == s.charAt(j)) {
                next[j] = i + 1;
                i++;
                j++;
            } else {
                if (i == 0) {
                    next[j] = 0;
                    j++;

                }else {
                    // 将下表跳转到之前相同的位置
                    i = next[i - 1];
                }

            }
        }
        return next;
    }

    @Test
    public void test() {
        String haystack = "bbcabcdababcdabcdabde", needle = "abcdabd";
        System.out.println(strStr(haystack, needle));
    }

    @Test
    public void test1() {
        String haystack = "bbcabbababc", needle = "ababc";
        System.out.println(strStr(haystack, needle));
    }
}
